struct mystack
{
    double* arr = 0;
    int index_of_free_place = 0;
    const int max_size = 100;
};


int stackOK (struct mystack*);      //! The function 'stackOK' checks the stack
void stack_dump (struct mystack*);  //! The function 'dump' prints data if the stack is bad
int push (struct mystack*);         //! The function 'push' pushes input number to the stack
int pop (struct mystack*);          //! The function 'pop' deletes the top element of the stack and prints it
int add (struct mystack*);          //! The function 'add' calculates the sum of two numbers
int mul (struct mystack*);          //! The function 'mul' calculates the multiplication of two number
int sub (struct mystack*);          //! The function 'sub' calculates the subtraction of two numbers
int div (struct mystack*);          //! The function 'div' calculates the division of two numbers
int destruct (struct mystack*);     //! The function 'END' deletes stack and finishes the program


/*Description of errors*/
const int HAPPINESS     = 0; /*No errors*/
const int TOO_MANY      = 1; /*Too many numbers in stack*/
const int TOO_FEW       = 2; /*Too few numbers in stack*/
const int WRONG_COMMAND = 3; /*Input command doesn't exist*/
const int DIVISION_ZERO = 4; /*Division by zero*/
const int BAD_STACK     = 5; /*Stack is bad*/
/*Other errors are controlled by asserts*/



int stackOK (struct mystack* const ptr_stack)
{
    assert (("ERROR. POINTER TO STACK IS ZERO!", ptr_stack));

    if ( (*ptr_stack).index_of_free_place < 0 || (*ptr_stack).index_of_free_place >= (*ptr_stack).max_size || *((*ptr_stack).arr + (*ptr_stack).index_of_free_place) != -100 )
    {
        stack_dump (ptr_stack);
        return BAD_STACK;
    }

    else
        return HAPPINESS;
}


void stack_dump (struct mystack* const ptr_stack)
{
    assert (("ERROR. POINTER TO STACK IS ZERO!", ptr_stack));

    printf ("Stack is bad!\n");
    printf ("stack_dump [%p]\n{\n", (*ptr_stack).arr);
    printf ("count = %d\n", (*ptr_stack).index_of_free_place);

    int max_size = (*ptr_stack).max_size;
    for (int i = 0; i < max_size; i++)
    {
        if (i < (*ptr_stack).index_of_free_place)
            printf ("   arr [%d] = %lg*\n", i, *((*ptr_stack).arr + i) );
        else
            printf ("   arr [%d] = %lg\n", i, *((*ptr_stack).arr + i) );
    }
    printf ("}\n");
}


int push (struct mystack* const ptr_stack)
{
    assert (("ERROR. POINTER TO STACK IS ZERO!", ptr_stack));
    assert (!stackOK (ptr_stack));

    if (scanf ("%lg", (*ptr_stack).arr + (*ptr_stack).index_of_free_place) != 1)
    {
        stack_dump (ptr_stack);
        return TOO_MANY;
    }

    (*ptr_stack).index_of_free_place++;

    assert (!stackOK (ptr_stack));
    return HAPPINESS;
}


int pop (struct mystack* const ptr_stack)
{
    assert (("ERROR. POINTER TO STACK IS ZERO!", ptr_stack));
    assert (!stackOK (ptr_stack));

    if ((*ptr_stack).index_of_free_place < 1)
    {
        stack_dump (ptr_stack);
        return TOO_FEW;
    }

    (*ptr_stack).index_of_free_place--;
    printf ("%lg\n", *( (*ptr_stack).arr + (*ptr_stack).index_of_free_place) );

    *((*ptr_stack).arr + (*ptr_stack).index_of_free_place) = -100;
    assert (!stackOK (ptr_stack));
    return HAPPINESS;
}


int add (struct mystack* const ptr_stack)
{
    assert (("ERROR. POINTER TO STACK IS ZERO!", ptr_stack));
    assert (!stackOK (ptr_stack));

    if ((*ptr_stack).index_of_free_place <= 1)
    {
        stack_dump (ptr_stack);
        return TOO_FEW;
    }

    (*ptr_stack).index_of_free_place--;
    *((*ptr_stack).arr + (*ptr_stack).index_of_free_place - 1) += *((*ptr_stack).arr + (*ptr_stack).index_of_free_place);

    *((*ptr_stack).arr + (*ptr_stack).index_of_free_place) = -100;
    assert (!stackOK (ptr_stack));
    return HAPPINESS;
}


int mul (struct mystack* const ptr_stack)
{
    assert (("ERROR. POINTER TO STACK IS ZERO!", ptr_stack));
    assert (!stackOK (ptr_stack));

    if ((*ptr_stack).index_of_free_place <= 1)
    {
        stack_dump (ptr_stack);
        return TOO_FEW;
    }

    (*ptr_stack).index_of_free_place--;
    *((*ptr_stack).arr + (*ptr_stack).index_of_free_place - 1) *= *((*ptr_stack).arr + (*ptr_stack).index_of_free_place);

    *((*ptr_stack).arr + (*ptr_stack).index_of_free_place) = -100;
    assert (!stackOK (ptr_stack));
    return HAPPINESS;
}


int sub (struct mystack* const ptr_stack)
{
    assert (("ERROR. POINTER TO STACK IS ZERO!", ptr_stack));
    assert (!stackOK (ptr_stack));

    if ((*ptr_stack).index_of_free_place <= 1)
    {
        stack_dump (ptr_stack);
        return TOO_FEW;
    }

    (*ptr_stack).index_of_free_place--;
    *((*ptr_stack).arr + (*ptr_stack).index_of_free_place - 1) -= *((*ptr_stack).arr + (*ptr_stack).index_of_free_place);

    *((*ptr_stack).arr + (*ptr_stack).index_of_free_place) = -100;
    assert (!stackOK (ptr_stack));
    return HAPPINESS;
}


int div (struct mystack* const ptr_stack)
{
    assert (("ERROR. POINTER TO STACK IS ZERO!", ptr_stack));
    assert (!stackOK (ptr_stack));

    if ((*ptr_stack).index_of_free_place <= 1)
    {
        stack_dump (ptr_stack);
        return TOO_FEW;
    }

    if ( fabs ( *((*ptr_stack).arr + (*ptr_stack).index_of_free_place - 1) ) <= DBL_EPSILON)
    {
        stack_dump (ptr_stack);
        return DIVISION_ZERO;
    }

    (*ptr_stack).index_of_free_place--;
    *((*ptr_stack).arr + (*ptr_stack).index_of_free_place - 1) /= *((*ptr_stack).arr + (*ptr_stack).index_of_free_place);

    *((*ptr_stack).arr + (*ptr_stack).index_of_free_place) = -100;
    assert (!stackOK (ptr_stack));
    return HAPPINESS;
}


int destruct (struct mystack* ptr_stack)
{
    assert (("ERROR. POINTER TO STACK IS ZERO!", ptr_stack));
    assert (!stackOK (ptr_stack));

    for (int i = 0; i < 100; i++) *((*ptr_stack).arr + i) = -100;
    (*ptr_stack).index_of_free_place = -1;
    free ((*ptr_stack).arr);
    (*ptr_stack).arr = 0;
    ptr_stack = 0;

    return -1;
}
